package com.coolxiaoyao.common.util;

import com.coolxiaoyao.common.annotation.PathVariable;
import com.coolxiaoyao.common.annotation.RequestParam;
import org.jetbrains.annotations.NotNull;
import org.reflections.Reflections;

import java.lang.annotation.Annotation;
import java.util.*;

/**
 * @author Kerry on 18/09/20
 */

public class ClassUtil {

    @NotNull
    public static Set<Class<?>> scannerClassByAnnotation(Class<? extends Annotation> annotationClass, String... primaryPackages) {
        if (primaryPackages.length == 0) {
            return Collections.emptySet();
        }
        String[] ps = new String[primaryPackages.length];
        for (int i = 0; i < primaryPackages.length; i++) {
            ps[i] = primaryPackages[i];
        }
        return scannerClassByAnnotationPackage(annotationClass, ps);
    }


    @NotNull
    public static Set<Class<?>> scannerClassByAnnotation(Class<? extends Annotation> annotationClass, Class<?>... primaryClass) {
        if (primaryClass.length == 0) {
            return Collections.emptySet();
        }
        String[] pkgs = new String[primaryClass.length];
        for (int i = 0; i < primaryClass.length; i++) {
            pkgs[i] = primaryClass[i].getPackage().getName();
        }
        return scannerClassByAnnotation(annotationClass, pkgs);
    }

    @NotNull
    public static Set<Class<?>> scannerClassByAnnotationPackage(Class<? extends Annotation> annotationClass, String[] primaryPkg) {
        Set<Class<?>> allClass = new HashSet<>();
        for (String pkg : primaryPkg) {
            Reflections reflections = new Reflections(pkg);
            Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(annotationClass);
            allClass.addAll(typesAnnotatedWith);
        }
        return allClass;
    }


    public static boolean supportRequestBodyClassType(Class<?> type) {
        if (type.isPrimitive()) {
            return false;
        } else if (Number.class.isAssignableFrom(type)) {
            return false;
        } else if (type == String.class) {
            return true;
        } else if (type == List.class) {
            return true;
        } else if (type == Map.class) {
            return true;
        }
        return true;
    }


    /**
     * 支持的对象
     *
     * @param type
     * @return
     * @see RequestParam 支持的对象
     */
    public static boolean supportRequestParamClassType(Class<?> type) {
        if (type.isPrimitive()) {
            return true;
        } else if (Number.class.isAssignableFrom(type)) {
            return true;
        } else if (type.isArray()) {
            return true;
        } else if (List.class.isAssignableFrom(type)) {
            return true;
        } else {
            return type == String.class;
        }
    }


    /**
     * com.coolxiaoyao.common.annotation.PathVariable 支持的类似类型
     *
     * @param type
     * @return
     * @see PathVariable
     */
    public static boolean supportPathVariableClassType(Class<?> type) {
        if (type == Boolean.TYPE || type == Integer.TYPE ||
                type == Short.TYPE || type == Float.TYPE ||
                type == Double.TYPE || type == Byte.TYPE
                || type == Long.TYPE || type == Character.TYPE) {
            return true;
        } else if (Number.class.isAssignableFrom(type)) {
            return true;
        } else {
            return type == String.class;
        }
    }


    public static Object[] getObjectArrayDefaultValue(Class<?>[] cs) {
        Object[] args = new Object[cs.length];
        for (int i = 0; i < cs.length; i++) {
            args[i] = getObjectDefaultValue(cs[i]);
        }
        return args;
    }

    /**
     * 通过类获取默认值
     *
     * @param clazz
     * @return
     */
    public static Object getObjectDefaultValue(Class<?> clazz) {
        if (clazz.isPrimitive()) {
            if (clazz == Byte.TYPE || clazz == Integer.TYPE || clazz == Long.TYPE || clazz == Short.TYPE) {
                return 0;
            } else if (clazz == Double.TYPE) {
                return 0.0;
            } else if (clazz == Float.TYPE) {
                return 0.0f;
            } else if (clazz == Boolean.TYPE) {
                return false;
            } else if (clazz == Character.TYPE) {
                return '\0';
            }
        }
        return null;
    }


    public static Object convertValueByClass(Class<?> clazz, String value) {
        if (clazz.isPrimitive()) {
            if (clazz == Byte.TYPE) {
                return Byte.parseByte(value);
            } else if (clazz == Integer.TYPE) {
                return Integer.parseInt(value);
            } else if (clazz == Long.TYPE) {
                return Long.parseLong(value);
            } else if (clazz == Short.TYPE) {
                return Short.parseShort(value);
            } else if (clazz == Double.TYPE) {
                return Double.parseDouble(value);
            } else if (clazz == Float.TYPE) {
                return Float.parseFloat(value);
            } else if (clazz == Boolean.TYPE) {
                return Boolean.parseBoolean(value);
            } else if (clazz == Character.TYPE) {
                if (value.length() > 0) {
                    return value.toCharArray()[0];
                }
                return '\0';
            }
        } else if (clazz == Integer.class) {
            return Integer.valueOf(value);
        } else if (clazz == Long.class) {
            return Long.valueOf(value);
        } else if (clazz == Short.class) {
            return Short.valueOf(value);
        } else if (clazz == Boolean.class) {
            return Boolean.valueOf(value);
        } else if (clazz == Float.class) {
            return Float.valueOf(value);
        } else if (clazz == Double.class) {
            return Double.valueOf(value);
        } else if (clazz == Byte.class) {
            return Byte.valueOf(value);
        } else if (clazz == Character.class) {
            if (value.length() > 0) {
                return value.toCharArray()[0];
            }
            return '\0';
        }
        return value;
    }


}
